package org.refresh.prolog;

import java.util.Collections;
import java.util.Hashtable;
import java.util.List;

import org.refresh.core.intelligence.Constraint;
import org.refresh.core.intelligence.ConstraintEvaluator;
import org.refresh.core.intelligence.KBManager;
import org.refresh.core.intelligence.ObjectView;
import org.refresh.core.intelligence.QueryEvaluator;
import org.refresh.core.intelligence.RefreshKB;

/******************************************************************************
 * Copyright (c) 2005, 2006 Jules White.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Jules White - initial API and implementation 
 ****************************************************************************/
public class PrologEvaluator implements ConstraintEvaluator, QueryEvaluator, KBManager {

	private KnowledgeBase kb_;
	private RefreshKB refresh_;
	private ObjectManager objectManager_;
	private Prolog prolog_;
	private PrologConverter converter_ = new BasicPrologConverter();
	
	public PrologEvaluator(RefreshKB ref){
		prolog_ = new Prolog();
		PrologAssertionManager mgr = new PrologAssertionManager();
		mgr.setProlog(prolog_);
		objectManager_ = new BasicObjectManager();
		kb_ = new KnowledgeBase(mgr,objectManager_);
		refresh_ = ref;
	}
	
	public boolean evaluate(Object src, Object trg, Constraint constraint) {
		PrologConstraint pcon = (PrologConstraint)constraint;
		String prolog = pcon.getCode();
		
		String selfid = objectManager_.getId(src);
		String trgid = objectManager_.getId(trg);
		prolog = populateSelf(prolog, selfid);
		prolog = populateTarget(prolog, trgid);
		prolog += ".";
		ensureLoaded(pcon);
		if(prolog_.query(prolog)){
			return true;
		}
		else{
			return false;
		}
	}

	public List findAll(Object src, List world, List<Constraint> cons) {
		String selfid = objectManager_.getId(src);
		String prolog = "findall(RefreshObj,(";
		for(Constraint con : cons){
			PrologConstraint pcon = (PrologConstraint)con;
			ensureLoaded(pcon);
			prolog += populateSelf(pcon.getCode(),selfid)+",";
		}
		prolog = prolog.substring(0,prolog.length()-1);
		prolog += "),RefreshResult).";
		
		if(prolog_.query(prolog)){
			Hashtable sol = prolog_.nextSolution();
			Object result = sol.get("RefreshResult");
			return (List)converter_.toObject(objectManager_, ""+result);
		}
		else{
			return Collections.emptyList();
		}
	}
	
	public String populateSelf(String rule, String selfid){
		return rule.replaceAll("Self", selfid);
	}
	
	public String populateTarget(String rule, String targetid){
		return rule.replaceAll("Target", targetid);
	}
	
	public void ensureLoaded(PrologConstraint pcon){
		
	}

	/* (non-Javadoc)
	 * @see org.refresh.core.intelligence.KBManager#add(java.lang.Object, org.refresh.core.intelligence.ObjectView)
	 */
	public void add(Object obj, ObjectView view) {
		kb_.add(obj, refresh_.findObjectTypes(obj), view,refresh_.getKnowledgeBase());
	}

	/* (non-Javadoc)
	 * @see org.refresh.core.intelligence.KBManager#remove(java.lang.Object, org.refresh.core.intelligence.ObjectView)
	 */
	public void remove(Object obj, ObjectView view) {
		kb_.remove(obj);
	}

	/**
	 * @return the kb
	 */
	public KnowledgeBase getKB() {
		return kb_;
	}

	/**
	 * @param kb the kb to set
	 */
	public void setKB(KnowledgeBase kb) {
		kb_ = kb;
	}

	
}
